//
// Copyright (c) 2009-2010 by Patrick Goebel, patrick@pirobot.org
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;

namespace MyRobot
{
    public partial class MyRobot : Form
    {
        public MyRobot()
        {
            InitializeComponent();
        }

        #region Declarations

        // The GUI class that represents our user interface components.
        public static GUI myGUI = new GUI();

        // The Nodes class contains all our methods and properties for running processes, 
        // reading sensors, and controlling motors.
        public static BaseNodes myNodes;

        // A hashtable that will store the names of the controls on our form(s) so we can reference them from other classes by name.
        public static Hashtable controlHashtable = new Hashtable();

        // The current Rovio speeds.
        public static int RovioSpeed, RovioTurnSpeed, RovioCourage;

        public string debugMessage = "";

        // These codes come from the RoboRealm interface to the Rovio.
        public enum RovioDriveCodes: int
        {
            Stop = 0,
            Forward = 1,
            Backward = 2,
            Left = 3,
            Right = 4,
            RotateLeft = 5,
            RotateRight = 6,
            DiagonalForwardLeft = 7,
            DiagonalForwardRight = 8,
            DiagonalBackwardLeft = 9,
            DiagonalBackwardRight = 10,
            HeadUp = 11,
            HeadDown = 12,
            HeadMiddle = 13,
            RotateLeft20 = 17,
            RotateRight20 = 18
        }

        private Control GetControlByName(string name)
        {
            return controlHashtable[name] as Control;
        }

        #endregion

        #region Form Load
        private void Rovio_Load(object sender, EventArgs e)
        {
            // Create a string-indexed hash table for the controls on this form for easy reference since C# only indexes controls by integers.
            foreach (Control c in this.Controls) controlHashtable.Add(c.Name, c);

            // Create our base nodes.
            myNodes = new BaseNodes();

            // Note that Rovio uses 1 for the fastest speed and 10 for the slowest, so we
            // invert the value here to make the GUI control more intuitive.
            RovioSpeed = 11 - (int)RovioSpeedControl.Value;
            RovioTurnSpeed = 11 - (int)RovioTurnSpeedControl.Value;
        }
        #endregion

        #region Form Closing
        private void Rovio_FormClosing(object sender, FormClosingEventArgs e)
        {
            try { myNodes.Roam.Thread.Abort(); }
            catch { }
            myNodes.RoboRealm.RovioDrive(RovioDriveCodes.Stop, 0);
            Thread.Sleep(1000);
            try { myNodes.RoboRealm.Thread.Abort(); }
            catch { }
        }
        #endregion

        #region Form Buttons
        private void RoamButton_Click(object sender, EventArgs e)
        {
            myNodes.Roam.Run();
            myNodes.RoboRealm.SetVariable("ACTION", "");
        }

        private void StopRoam_Click(object sender, EventArgs e)
        {
            StopRovioCompletely();
        }

        private void StopRovioCompletely()
        {
            SensorTimer.Stop();
            myNodes.Roam.Stop();
            try {
                myNodes.Roam.Thread.Join();
            }
            catch { }
            myNodes.RoboRealm.RovioDrive(RovioDriveCodes.Stop, 0);
            RoamButton.Enabled = false;
        }

        private void StopRovio()
        {
            myNodes.RoboRealm.RovioDrive(RovioDriveCodes.Stop, 0);
        }

        private void DriveStopButton_Click(object sender, EventArgs e)
        {
            StopRovioCompletely();
        }

        private void HeadUpDown_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (HeadUpDown.SelectedIndex == 0)
            {
                myNodes.RoboRealm.RovioDrive(RovioDriveCodes.HeadDown, 10);
            }
            else if (HeadUpDown.SelectedIndex == 1)
            {
                myNodes.RoboRealm.RovioDrive(RovioDriveCodes.HeadMiddle, 10);
            }
            else if (HeadUpDown.SelectedIndex == 2)
            {
                myNodes.RoboRealm.RovioDrive(RovioDriveCodes.HeadUp, 10);
            }
        }

        private void RovioSpeedControl_ValueChanged(object sender, EventArgs e)
        {
            RovioSpeed = 11 - (int)RovioSpeedControl.Value;
        }

        private void RovioTurnSpeedControl_ValueChanged(object sender, EventArgs e)
        {
            RovioTurnSpeed  = 11 - (int)RovioTurnSpeedControl.Value;
        }

        private void StartButton_Click(object sender, EventArgs e)
        {
            SensorTimer.Start();
            myNodes.RoboRealm.Run();
            RoamButton.Enabled = true;
        }
        #endregion

        #region Form Timer
        private void FormTimer_Tick(object sender, EventArgs e)
        {
            if (myNodes.myRovio.Properties.Radar.Properties.Value == 1)
            {
                wvRadar.BackColor = Color.Green;
                wvRadar.Checked = true;
            }
            else
            {
                wvRadar.BackColor = Color.Silver;
                wvRadar.Checked = false;
            }
        }
        #endregion

        #region Manual Drive Buttons
        private void DriveForwardButton_MouseDown(object sender, MouseEventArgs e)
        {
            myNodes.RoboRealm.RovioDrive(RovioDriveCodes.Forward, RovioSpeed);
        }

        private void DriveReverseButton_MouseDown(object sender, MouseEventArgs e)
        {
            myNodes.RoboRealm.RovioDrive(RovioDriveCodes.Backward, RovioSpeed);
        }

        private void DriveRotateLeftButton_MouseDown(object sender, MouseEventArgs e)
        {
            myNodes.RoboRealm.RovioDrive(RovioDriveCodes.RotateLeft, RovioTurnSpeed);
        }

        private void DriveRotateRightButton_MouseDown(object sender, MouseEventArgs e)
        {
            myNodes.RoboRealm.RovioDrive(RovioDriveCodes.RotateRight, RovioTurnSpeed);
        }

        private void DriveCrabLeftButton_MouseDown(object sender, MouseEventArgs e)
        {
            myNodes.RoboRealm.RovioDrive(RovioDriveCodes.DiagonalBackwardLeft, RovioTurnSpeed);
        }

        private void DriveCrabRightButton_MouseDown(object sender, MouseEventArgs e)
        {
            myNodes.RoboRealm.RovioDrive(RovioDriveCodes.DiagonalBackwardRight, RovioTurnSpeed);
        }

        private void DriveCrabLeftForward_MouseDown(object sender, MouseEventArgs e)
        {
            myNodes.RoboRealm.RovioDrive(RovioDriveCodes.DiagonalForwardLeft, RovioTurnSpeed);
        }

        private void DriveCrabRightForward_MouseDown(object sender, MouseEventArgs e)
        {
            myNodes.RoboRealm.RovioDrive(RovioDriveCodes.DiagonalForwardRight, RovioTurnSpeed);
        }

        private void DriveLeft_MouseDown(object sender, MouseEventArgs e)
        {
            myNodes.RoboRealm.RovioDrive(RovioDriveCodes.Left, RovioTurnSpeed);
        }

        private void DriveRight_MouseDown(object sender, MouseEventArgs e)
        {
            myNodes.RoboRealm.RovioDrive(RovioDriveCodes.Right, RovioTurnSpeed);
        }

        private void DriveCrabLeftForward_MouseUp(object sender, MouseEventArgs e)
        {
            StopRovio();
        }

        private void DriveForwardButton_MouseUp(object sender, MouseEventArgs e)
        {
            StopRovio();
        }

        private void DriveCrabRightForward_MouseUp(object sender, MouseEventArgs e)
        {
            StopRovio();
        }

        private void DriveLeft_MouseUp(object sender, MouseEventArgs e)
        {
            StopRovio();
        }

        private void DriveRight_MouseUp(object sender, MouseEventArgs e)
        {
            StopRovio();
        }

        private void DriveRotateLeftButton_MouseUp(object sender, MouseEventArgs e)
        {
            StopRovio();
        }

        private void DriveRotateRightButton_MouseUp(object sender, MouseEventArgs e)
        {
            StopRovio();
        }

        private void DriveCrabLeftBackward_MouseUp(object sender, MouseEventArgs e)
        {
            StopRovio();
        }

        private void DriveBackwardButton_MouseUp(object sender, MouseEventArgs e)
        {
            StopRovio();
        }

        private void DriveCrabRightBackward_MouseUp(object sender, MouseEventArgs e)
        {
            StopRovio();
        }
        #endregion

        private void SpeechEnabled_CheckedChanged(object sender, EventArgs e)
        {
            if (SpeechEnabled.Checked) myNodes.RoboRealm.SetVariable("SPEECH_ENABLED", "YES");
            else myNodes.RoboRealm.SetVariable("SPEECH_ENABLED", "NO");
        }

        private void RovioCourageControl_ValueChanged(object sender, EventArgs e)
        {
            RovioCourage = (int)RovioCourageControl.Value;
        }

        //private void DockRovio_Click(object sender, EventArgs e)
        //{
        //    StopRovioCompletely();
        //    myNodes.RoboRealm.SetVariable("ROVIO_DOCK", "dock");
        //}
    }
}